package multithread.framework.xml;

import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import multithread.framework.annotation.ThreadAfter;
import multithread.framework.annotation.ThreadAllAfter;
import multithread.framework.annotation.ThreadAllBefore;
import multithread.framework.annotation.ThreadBefore;
import multithread.framework.annotation.ThreadGroupAfter;
import multithread.framework.annotation.ThreadGroupBefore;
import multithread.framework.constant.XMLConfigConstant;

import org.jdom.Comment;
import org.jdom.Element;

public class CommonElement extends Element implements IVerifiable {
	private static final long serialVersionUID = -6233709490854334354L;

	/**
	 * store element such as {@link XMLConfigConstant.ALLBEFORE_ELEMENT}
	 */
	private Map<Class<? extends Annotation>, Element> childElements;

	public CommonElement() {
		super(XMLConfigConstant.COMMON_ELEMENT);
		childElements = new HashMap<Class<? extends Annotation>, Element>();
	}

	/**
	 * add method element to common element by Element annotation class type
	 * 
	 * @param methodElement
	 *            MethodElement
	 * @param annotationClz
	 *            Class<? extends Annotation>
	 * @return Element
	 */
	public Element addMethodElement(MethodElement methodElement,
			Class<? extends Annotation> annotationClz) {
		if (annotationClz == ThreadAllBefore.class) {
			return addMethodElement(methodElement, ThreadAllBefore.class,
					XMLConfigConstant.ALLBEFORE_ELEMENT);
		} else if (annotationClz == ThreadAllAfter.class) {
			return addMethodElement(methodElement, ThreadAllAfter.class,
					XMLConfigConstant.ALLAFTER_ELEMENT);
		} else if (annotationClz == ThreadGroupBefore.class) {
			return addMethodElement(methodElement, ThreadGroupBefore.class,
					XMLConfigConstant.GROUPBEFORE_ELEMENT);
		} else if (annotationClz == ThreadGroupAfter.class) {
			return addMethodElement(methodElement, ThreadGroupAfter.class,
					XMLConfigConstant.GROUPAFTER_ELEMENT);
		} else if (annotationClz == ThreadBefore.class) {
			return addMethodElement(methodElement, ThreadBefore.class,
					XMLConfigConstant.BEFORE_ELEMENT);
		} else if (annotationClz == ThreadAfter.class) {
			return addMethodElement(methodElement, ThreadAfter.class,
					XMLConfigConstant.AFTER_ELEMENT);
		}
		return null;
	}

	private Element addMethodElement(MethodElement methodElement,
			Class<? extends Annotation> annotationClz, String elementName) {
		if (methodElement != null) {
			Element childElement = childElements.get(annotationClz);
			// check exist
			if (childElement == null) {
				addContent(new Comment(annotationClz.getSimpleName()));
				childElement = new Element(elementName);
				Element methods = new Element(XMLConfigConstant.MEHTODS_ELEMENT);
				childElement.addContent(methods);
				addContent(childElement);
				childElements.put(annotationClz, childElement);
			}
			Element methods = childElement
					.getChild(XMLConfigConstant.MEHTODS_ELEMENT);
			if (methods != null) {
				return methods.addContent(methodElement);
			}
		}
		return null;
	}

	@Override
	public boolean validate() {
		List<?> childlist = this.getChildren();
		return childlist == null ? false : childlist.size() > 0 ? true : false;
	}

}
